package gui;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Group;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.TitledBorder;

@SuppressWarnings("serial")
public class GUIManager extends JFrame {
	protected GroupLayout layout;
	
	/**
	 * Elements registered to be drawn. If a block type is not registered it will be replaced by 
	 * an empty stub.
	 */
	protected Map<BlockType, Element> elementsRegistered = new HashMap<BlockType, Element>();
	
	/**
	 * Blocks which are ready to be placed in to layout (including empty stubs).
	 */
	protected Map<BlockType, Element> layoutBlocks = new HashMap<BlockType, Element>();

	public GUIManager() {
		super("Nyan-Temperature");
		setDefaultCloseOperation(EXIT_ON_CLOSE);
	}

	/**
	 * Prepares the layout components. Invoke after registering!
	 */
	public void initComponents() {
		JPanel rootPanel = new JPanel();
		layout = new GroupLayout(rootPanel);
		setContentPane(rootPanel);
		getContentPane().setLayout(layout);

		for (Element e : elementsRegistered.values()) {
			e.init();
		}

		prepareBlocks();
		injectBlocks();

		pack(); //Resizes the window
	}

	/**
	 * Check if a block is registered. Create missing ones. 
	 */
	protected void prepareBlocks() {
		for (BlockType type : getSortedBlockTypes()) {
			if (elementsRegistered.containsKey(type)) { // If block registered
				insertElementIntoLayout(elementsRegistered.get(type), type);
			} else {
			//	insertBlankElementIntoLayout(type);
			}
		}
	}
	
	protected Collection<BlockType> getSortedBlockTypes() {
		List<BlockType> types = new ArrayList<BlockType>();
		types.add(BlockType.Chart);
		types.add(BlockType.CurrentMeasurment);
		types.add(BlockType.NyanCat);
		types.add(BlockType.ControlPanel);
		
		return types;
	}
	
	/**
	 * Arrange blocks in a layout. 
	 */	
	protected void injectBlocks() {
		Group leftGroup = layout.createParallelGroup(GroupLayout.Alignment.CENTER);
		Group leftVerticalGroup = layout.createSequentialGroup();

		Group rightGroup = layout.createParallelGroup();
		Group rightVerticalGroup = layout.createSequentialGroup();

		layout.setHorizontalGroup(layout.createSequentialGroup()
				.addGroup(leftGroup).addGroup(rightGroup));
		layout.setVerticalGroup(layout.createParallelGroup()
				.addGroup(leftVerticalGroup).addGroup(rightVerticalGroup));

		for (BlockType type : getSortedBlockTypes()) {
			Element el = layoutBlocks.get(type);
			JComponent block = el.getComponent();
			if (el.isLeftPanel()) {
				leftGroup.addComponent(block);
				leftVerticalGroup.addComponent(block);
			} else {
				rightGroup.addComponent(block);
				rightVerticalGroup.addComponent(block);
			}
		}
	}


	/**
	 * Puts the element into the layout blocks collection. If a non-empty caption is provided
	 * it creates a titled border around the component.
	 * @param e Element to be inserted
	 * @param type Block type of the element
	 */
	protected void insertElementIntoLayout(Element e, BlockType type) {
		layoutBlocks.put(type, e);
		if (!e.getCaption().isEmpty()) {
			e.getComponent().setBorder(new TitledBorder(e.getCaption()));
		}

	}
	
	/**
	 * Creates a blank element and inserts it into the layout with a proper method 
	 * @param type
	 * @see insertElementIntoLayout
	 */
	protected void insertBlankElementIntoLayout(BlockType type) {
		// Just a stub
		Element blank = new Element() {
			JComponent blankElement = new JPanel();

			@Override
			public void init() {
				// do nth
			}

			@Override
			public JComponent getComponent() {
				return blankElement;
			}

			@Override
			public String getCaption() {
				return "Auto-Generated Stub";
			}

			@Override
			public boolean isLeftPanel() {
				return true;
			}
		};
		blank.getComponent().add(new JButton("Change me: " + type.toString()));
		insertElementIntoLayout(blank, type);
	}
	
	/**
	 * Registers element in to the gui
	 * @param element
	 * @param type
	 */
	public void registerElement(Element element, BlockType type) {
		elementsRegistered.put(type, element);
	}

}
